package com.mall.common.service.impl;

import static com.mall.common.bean.CommonAttributes.PATH_SEPARATOR;

import java.util.List;

import javax.annotation.Resource;

import net.sf.json.JSONObject;

import org.hibernate.Hibernate;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.mall.common.dao.AreaDao;
import com.mall.common.domain.AreaDomain;
import com.mall.common.hibernate.Finder;
import com.mall.common.service.AreaService;


@Service
@Transactional
public class AreaServiceImpl extends BaseServiceImpl<AreaDomain, Long> implements AreaService {

	@Resource
	private AreaDao areaDao;

	@Resource
	public void setBaseDao(AreaDao areaDao) {
		super.setBaseDao(areaDao);
	}

	@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
	public List<AreaDomain> getRootAreaList() {
		List<AreaDomain> rootAreaList = areaDao.getRootAreaList();
		if (rootAreaList != null) {
			for (AreaDomain rootArea : rootAreaList) {
				Hibernate.initialize(rootArea);
			}
		}
		return rootAreaList;
	}
	
	@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
	public List<AreaDomain> getParentAreaList(AreaDomain area) {
		List<AreaDomain> parentAreaList = areaDao.getParentAreaList(area);
		if (parentAreaList != null) {
			for (AreaDomain parentArea : parentAreaList) {
				Hibernate.initialize(parentArea);
			}
		}
		return parentAreaList;
	}
	
	@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
	public List<AreaDomain> getChildrenAreaList(AreaDomain area) {
		List<AreaDomain> childrenAreaList = areaDao.getChildrenAreaList(area);
		if (childrenAreaList != null) {
			for (AreaDomain childrenArea : childrenAreaList) {
				Hibernate.initialize(childrenArea);
			}
		}
		return childrenAreaList;
	}
	
	@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
	public Boolean isNameUnique(Long parentId, String oldName, String newName) {
		return areaDao.isNameUnique(parentId, oldName, newName);
	}
	
	@Override
	@Transactional(propagation=Propagation.REQUIRED)
	public void remove(AreaDomain entity) {
		AreaDomain parent = this.find(entity.getId()).getParent();
		if (parent != null) {
			entity.setPath(parent.getPath()+ parent.getId()+PATH_SEPARATOR);
			entity.setFull_name(parent.getFull_name() + entity.getName());
		} else {
			entity.setPath(PATH_SEPARATOR);
			entity.setFull_name(entity.getName());
		}
		super.remove(entity);
	}

	@Override
	@CacheEvict(value="area",allEntries=true)
	@Transactional(propagation=Propagation.REQUIRED)
	public void remove(Long id) {
		areaDao.remove(id);
	}
	
	@Override
	@Transactional(propagation=Propagation.REQUIRED)
	public void remove(Long[] ids) {
		super.remove(ids);
	}

	@Override
	@CacheEvict(value="area",allEntries=true)
	@Transactional(propagation=Propagation.REQUIRED)
	public void persist(AreaDomain entity) {
		super.persist(entity);
		AreaDomain parent = entity.getParent();
		if (parent != null) {
			entity.setPath(parent.getPath()+ parent.getId()+PATH_SEPARATOR);
			entity.setFull_name(parent.getFull_name() + entity.getName());
		} else {
			entity.setPath(PATH_SEPARATOR);
			entity.setFull_name(entity.getName());
		}
		super.update(entity);
	}

	@Override
	@Transactional(readOnly=true)
	@Cacheable(value="area", key="'area'+#parentId")
	public JSONObject getAreaByPath(Long parentId) {
		Finder finder = Finder.create("from AreaDomain bean");
		if(parentId != null){
			finder.append(" where bean.parent.id = :parentId");
			finder.setParam("parentId", parentId);
		}else{
			finder.append(" where bean.parent is null");
		}
		List<AreaDomain> areas = finder.findHQLList();
		JSONObject obj = new JSONObject();
		for (AreaDomain area : areas){
			obj.put(area.getId(), area.getName());
		}
		return obj;
	}

	@Override
	@CacheEvict(value="area",allEntries=true)
	@Transactional(propagation=Propagation.REQUIRED)
	public AreaDomain updateByUpdater(AreaDomain entity) {
		return super.updateByUpdater(entity);
	}

}
